#!/usr/bin/perl
use strict;
use warnings;
use POSIX qw(mkfifo);
use threads;
use File::Path;
use Config::IniFiles;
use Daemon::Generic;
use IO::File;
use File::Basename;
use Data::Dumper;
use Shell qw (touch);

use IO::Handle;

STDERR->autoflush(1);
newdaemon(
	progname        => 'logdispatcher',
	pidfile         => '/var/run/logdispatcher.pid',
	configfile      => '/etc/logdispatcher.conf',
	);

my $fifoDir=undef;
my @fifoList=();
my $VERSION="1.00";
my %cfg=undef;
my $timeout=undef;

sub gd_version {
    return $VERSION;
}

sub gd_preconfig {
    my ($self) = @_;
    tie %cfg, 'Config::IniFiles', ( -file => $self->{configfile} );
    die Dumper (%cfg)."\nConfig undefined ( file not Found ??? )" unless %cfg;

    $fifoDir=$cfg{General}{fifoDirectory};
    die Dumper ($cfg{'General'})."\nGeneral -> fifoDirectory not set in config." unless defined $fifoDir;

    @fifoList=split ',', $cfg{General}{fifoNames};
    die Dumper ($cfg{'General'})."\nGeneral -> fifoList is empty : General->fifoNames" unless scalar @fifoList > 0;

    $timeout=$cfg{General}{timeout};
    die Dumper ($cfg{'General'})."\nGeneral -> timeout is empty : General->timeout" unless $timeout;

# Check fifo directory
    unless (-d $fifoDir) { 
	eval {mkpath ($fifoDir)};
	if ($@){
	    die "Can't make $fifoDir directory....";
	}
    } 

#Check fifo Creation
    foreach my $fifoFile ( @fifoList ) {
	my $fifoName="$fifoDir/$fifoFile";
	unless (-p $fifoName) {
	    eval { mkfifo($fifoName, 777); };
	    if ($@){
		die " Can't make Fifo file : $fifoFile \n $@";
	    }
	}
    }

    return ( config => \%cfg ) ;
}
my $run;
sub gd_run {
	$run=1;
    my $i=0;
# Spawn thread
    foreach my $fifoFile (@fifoList) {
	eval {threads->create ( "handleFifo",  ($i, $fifoFile))};
	$i++;
    }

# boucle
    do { sleep ($timeout); }while($run);
}

sub gd_setup_signals{
      $run=0;
}

sub handleFifo {
    my $id = shift;
    my $facility=shift;
    my $fifo = "$fifoDir/".$facility;

    my $localCfg=$cfg{$facility};

    die ("No configuration item for $facility") if scalar keys %$localCfg==0;
# Open all local files
#print Dumper $localCfg;
    my %patternHandlers=();
    my %patternFilenames=();
    while ( my ($pattern, $dest) = each(%$localCfg) ) {
	if ($dest =~ /file:\/\/(.*)/) {
	    unless ( -d dirname($1) ) {
		print STDERR "$1 doesn't exists !!!!";
		eval { mkpath  dirname($1) };
		die  dirname($1) ." can't be created : $@" if ($@);
	    }

	    $patternFilenames{$pattern}=$1;
	    $patternHandlers{$pattern}=undef;
	    print STDERR "* Thread $id : sending log to $1 for $pattern\n";
	}
    }

    do {
    	my $syslog = new IO::File;
    	open ($syslog, "+<$fifo") || die "Couldn't open $fifo: $!\n";
	while (<$syslog>) {
	    my $line=$_;
	    #print STDERR "$id => $line";
	    while ( my ($p, $h) = each(%patternHandlers) ) {
		#print STDERR "$p matching $_" if $_ =~/$p/ ;
		#print STDERR "$p NOT matching $_" unless  $_ =~/$p/ ;
		#print  "$line" if $line =~/$p/;
		if ($line =~/$p/)
		{
			#print STDERR "$line\n";
			unless (defined $h and $h->opened) {
			  #  print STDERR $patternFilenames{$p}." to be opened...\n";
				$h=$patternHandlers{$p}=openFileHandle( $patternFilenames{$p});
				
			}
			#print STDERR "Handler for $p is defined....\n" if defined $h; 
			#print STDERR "Handler for $p is opened....\n" if $h->opened; 
			print $h "$line";
	    		$h->autoflush(1);
		}
	    }
	}
	sleep($timeout);
	$syslog->close;
    }while(1);
    print STDERR "END THREAD $id\n";
}

sub openFileHandle {
	    my $file=shift;
	    touch $file unless ( -f $file );
	    die "$file : $@" unless ( -f $file );
	    my $handle = new IO::File;
	    open($handle, ">>$file") or die "$file: $!";
	    $handle->autoflush(1);
	    return $handle;
}
